package org.javahispano.javacup.tacticas_aceptadas.hectord;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.JugadorDetalle;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;
import org.javahispano.javacup.modelo.Tactica;
import org.javahispano.javacup.modelo.TacticaDetalle;

public class TacticaCAT2_03 implements Tactica {

	Posicion alineacion1[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-1.902097902097902, -40.62217194570136),
			new Posicion(-23.538461538461537, -35.63348416289593), new Posicion(22.58741258741259, -34.68325791855204),
			new Posicion(8.083916083916083, -31.83257918552036), new Posicion(-9.272727272727272, -32.782805429864254),
			new Posicion(-18.307692307692307, -21.855203619909503),
			new Posicion(17.594405594405593, -22.092760180995477), new Posicion(-22.58741258741259, 1.900452488687783),
			new Posicion(0.0, -13.540723981900454), new Posicion(23.3006993006993, 2.3755656108597285) };

	Posicion alineacion2[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-0.7132867132867133, -37.77149321266968),
			new Posicion(-20.923076923076923, -33.257918552036195),
			new Posicion(22.58741258741259, -32.782805429864254),
			new Posicion(13.314685314685315, -23.042986425339365),
			new Posicion(-10.6993006993007, -22.805429864253394),
			new Posicion(-23.776223776223777, -8.076923076923077),
			new Posicion(23.776223776223777, -9.264705882352942), new Posicion(-20.20979020979021, 10.452488687782806),
			new Posicion(-0.4755244755244755, -2.6131221719457014), new Posicion(19.25874125874126, 9.97737556561086) };

	Posicion alineacion3[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-0.4755244755244755, -33.73303167420815),
			new Posicion(-20.685314685314687, -26.606334841628957),
			new Posicion(20.20979020979021, -27.31900452488688), new Posicion(8.797202797202797, -10.214932126696834),
			new Posicion(-7.37062937062937, -10.690045248868778),
			new Posicion(-24.251748251748253, 10.690045248868778), new Posicion(22.825174825174827, 9.027149321266968),
			new Posicion(-19.25874125874126, 32.07013574660634), new Posicion(-0.4755244755244755, 17.104072398190045),
			new Posicion(21.874125874125873, 32.30769230769231) };

	Posicion alineacion4[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-0.4755244755244755, -35.39592760180996),
			new Posicion(-20.20979020979021, -33.257918552036195),
			new Posicion(19.97202797202797, -32.782805429864254), new Posicion(8.321678321678322, -17.104072398190045),
			new Posicion(-12.601398601398602, -16.628959276018097),
			new Posicion(-24.965034965034967, -10.927601809954751),
			new Posicion(27.58041958041958, -10.690045248868778),
			new Posicion(-20.685314685314687, -0.23755656108597287),
			new Posicion(-0.4755244755244755, -0.7126696832579186),
			new Posicion(20.447552447552447, -0.23755656108597287) };

	Posicion alineacion5[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-0.4755244755244755, -35.39592760180996),
			new Posicion(-20.20979020979021, -33.257918552036195),
			new Posicion(19.97202797202797, -32.782805429864254), new Posicion(9.272727272727272, -23.042986425339365),
			new Posicion(-11.174825174825173, -22.805429864253394),
			new Posicion(-22.825174825174827, -10.690045248868778),
			new Posicion(22.825174825174827, -12.352941176470589),
			new Posicion(-9.748251748251748, -0.7126696832579186),
			new Posicion(-0.23776223776223776, -9.739819004524888),
			new Posicion(9.510489510489512, -0.9502262443438915) };

	TacticaDetalle detalle = new TacticaDetalleImpl();

	public TacticaDetalle getDetalle() {
		return detalle;
	}

	public Posicion[] getPosicionSaca(SituacionPartido sp) {
		return alineacion4;
	}

	public Posicion[] getPosicionRecive(SituacionPartido sp) {
		return alineacion5;
	}

	private static final double LINEA_ZONA_DEFENSA_Y = -Constantes.ANCHO_CAMPO_JUEGO / 3;
	private static final double LINEA_ZONA_ATAQUE_Y = Constantes.ANCHO_CAMPO_JUEGO / 3;

	private static final int ARQUERO = 0;
	private static final int LIBERO = 1;
	private static final int DEFENSOR_IZQ = 2;
	private static final int DEFENSOR_DER = 3;
	private static final int CINCO_DER = 4;
	private static final int CINCO_IZQ = 5;
	private static final int MEDIOCAMPISTA_IZQ = 6;
	private static final int MEDIOCAMPISTA_DER = 7;
	private static final int ENGANCHE = 9;
	private static final int DELANTERO_IZQ = 8;
	private static final int DELANTERO_DER = 10;

	private static final int DISTANCIA_MIN_PASE = 20;
	private static final int DISTANCIA_MIN_MARCA = 10;
	private static final int DISTANCIA_MIN_TIRO_ARCO = 20;

	// Variables de estado
	private boolean moverMediocampistas = true;
	private int cantIteracionesMoverMediocampistas = 25;
	private int iteracionSaqueArco = 0;
	private boolean estoyAtacando = false;
	private boolean paseJugador = false;
	private int jugPasePelota = -1;
	private Posicion posJugPasePelota = new Posicion();

	private boolean llevoLaPelota = false;
	private int jugLlevaPelota = -1;

	Random rand = new Random(System.currentTimeMillis());
	LinkedList<Comando> comandos = new LinkedList<Comando>();

	public List<Comando> ejecutar(SituacionPartido sp) {

		try {
			comandos.clear();
			Posicion[] misJugadores = sp.misJugadores();

			// Da Posiciones a los jugadores
			adoptarPosiciones(sp);

			// Ubicar el ARQUERO seg�n la posicion del balon
			posicionarArquero(sp);

			// Adoptar Tactica Defensa/Ataque
			if (sp.saco()) {

				// Sacar
				double distanciaPelotaArco = sp.balon().distancia(Constantes.centroArcoInf);

				if (distanciaPelotaArco <= Constantes.LARGO_AREA_CHICA) {

					// Saco desde el arco
					// Acomodo a los jugadores segun alineacion2 menos al
					// arquero
					for (int i = 1; i < 11; i++) {
						comandos.add(new ComandoIrA(i, alineacion2[i]));
					}
					// Llevo el arquero al lugar de saque
					comandos.add(new ComandoIrA(ARQUERO, sp.balon()));

					if (sp.balon().getX() <= 0) {
						// El arquero busca el delantero izquierdo
						calcularPase(sp, ARQUERO, DELANTERO_IZQ);
					} else {
						// El arquero busca el delantero derecho
						calcularPase(sp, ARQUERO, DELANTERO_DER);
					}

					iteracionSaqueArco = sp.iteracion();
					moverMediocampistas = false;

				} else {

					// Me fijo quien es el mas cercano sin tener en cuenta a los
					// 3
					// delanteros
					int indMasCercano = sp.balon().indiceMasCercano(misJugadores, DELANTERO_DER, DELANTERO_IZQ,
							ENGANCHE);

					// Mando al jugador a sacar
					comandos.add(new ComandoIrA(indMasCercano, sp.balon()));
					for (int i : sp.puedenRematar()) {

						if (sp.balon().getY() > LINEA_ZONA_ATAQUE_Y) {

							// Saque al enganche
							calcularPase(sp, i, ENGANCHE);

						} else if (sp.balon().getX() > 0) {

							// Saque de la derecha, pase al DELANTERO_DER
							calcularPase(sp, i, DELANTERO_DER);

						} else {

							// Saque de la izquierda, pase al DELANTERO_IZQ
							calcularPase(sp, i, DELANTERO_IZQ);

						}

					}

				}

			} else if (sp.puedenRematar().length == sp.puedenRematarRival().length) {

				// Nadie Tiene la pelota
				avanzarDelanteros(sp);

				// Los 2 m�s cercanos van a buscar el balon, no se tiene en
				// cuenta
				// al arquero
				int[] indMasCercanos = sp.balon().indicesMasCercanos(misJugadores, ARQUERO);
				comandos.add(new ComandoIrA(indMasCercanos[0], sp.balon()));
				comandos.add(new ComandoIrA(indMasCercanos[1], sp.balon()));

				// Si el arquero le dio un pase a los mediocampistas, estos van
				// a
				// buscar el balon
				// Solo se mueven los mediocampistas despues de iteraciones de
				// un
				// saque de arco.
				if (!moverMediocampistas) {
					if (sp.balon().getX() <= 0) {
						Posicion pos = new Posicion(sp.balon().getX(), misJugadores[MEDIOCAMPISTA_IZQ].getY());
						comandos.add(new ComandoIrA(MEDIOCAMPISTA_IZQ, pos));
					} else {
						Posicion pos = new Posicion(sp.balon().getX(), misJugadores[MEDIOCAMPISTA_DER].getY());
						comandos.add(new ComandoIrA(MEDIOCAMPISTA_DER, pos));
					}
				}

			} else if (sp.puedenRematar().length < sp.puedenRematarRival().length) {

				// Defender
				estoyAtacando = false;
				paseJugador = false;
				llevoLaPelota = false;

				int[] indMasCercanos = sp.balon().indicesMasCercanos(misJugadores, DEFENSOR_IZQ, DEFENSOR_DER);
				comandos.add(new ComandoIrA(indMasCercanos[0], sp.balon()));
				comandos.add(new ComandoIrA(indMasCercanos[1], sp.balon()));

			} else {

				// Atacar
				estoyAtacando = true;

				Posicion destino = null;
				double x = 0;
				double y = 0;

				for (int idxOrigen : sp.puedenRematar()) {

					switch (idxOrigen) {
					case ARQUERO:
					case LIBERO:
					case DEFENSOR_IZQ:
					case DEFENSOR_DER:
						// Despeja la pelota buscando al MEDIOCAMPISTA_DER o
						// MEDIOCAMPISTA_IZQ o al ENGANCHE
						despejar(sp, idxOrigen);
						break;

					case CINCO_DER:

						x = misJugadores[idxOrigen].getX();
						y = Constantes.centroArcoSup.getY();
						destino = new Posicion(x, y);

						darOrdenesJugadores(sp, misJugadores, idxOrigen, destino);

						break;

					case CINCO_IZQ:

						x = misJugadores[idxOrigen].getX();
						y = Constantes.centroArcoSup.getY();
						destino = new Posicion(x, y);

						darOrdenesJugadores(sp, misJugadores, idxOrigen, destino);

						break;

					case MEDIOCAMPISTA_IZQ:

						x = misJugadores[idxOrigen].getX();
						y = Constantes.centroArcoSup.getY();
						destino = new Posicion(x, y);

						darOrdenesJugadores(sp, misJugadores, idxOrigen, destino);

						break;

					case MEDIOCAMPISTA_DER:

						x = misJugadores[idxOrigen].getX();
						y = Constantes.centroArcoSup.getY();
						destino = new Posicion(x, y);

						darOrdenesJugadores(sp, misJugadores, idxOrigen, destino);

						break;

					case ENGANCHE:

						x = misJugadores[idxOrigen].getX();
						y = Constantes.centroArcoSup.getY();
						destino = new Posicion(x, y);

						darOrdenesJugadores(sp, misJugadores, idxOrigen, destino);

						break;

					case DELANTERO_IZQ:

						if (sp.balon().getY() < LINEA_ZONA_ATAQUE_Y) {
							x = misJugadores[idxOrigen].getX();
							y = Constantes.centroArcoSup.getY();
							destino = new Posicion(x, y);
						} else {
							destino = Constantes.centroArcoSup;
						}

						darOrdenesJugadores(sp, misJugadores, idxOrigen, destino);

						break;

					case DELANTERO_DER:

						if (sp.balon().getY() < LINEA_ZONA_ATAQUE_Y) {
							x = misJugadores[idxOrigen].getX();
							y = Constantes.centroArcoSup.getY();
							destino = new Posicion(x, y);
						} else {
							destino = Constantes.centroArcoSup;
						}

						darOrdenesJugadores(sp, misJugadores, idxOrigen, destino);

						break;
					}
				}

			}

			// Solo se mueven los mediocampistas despues de iteraciones de un
			// saque
			// de arco.
			if (sp.iteracion() - iteracionSaqueArco > cantIteracionesMoverMediocampistas) {
				moverMediocampistas = true;
			}

		} catch (Exception e) {
		}
		return comandos;
	}

	private void darOrdenesJugadores(SituacionPartido sp, Posicion[] misJugadores, int idxOrigen, Posicion destino) {
		if (puedeAvanzarConPelota(sp, idxOrigen, destino)) {

			// Ver Distancia al arco, si esta cerca del arco hay que
			// patear.

			double distOrigenArco = misJugadores[idxOrigen].distancia(Constantes.centroArcoSup);

			if (distOrigenArco < DISTANCIA_MIN_TIRO_ARCO * 1.5) {

				// Disparar al arco
				patearArco(sp, idxOrigen);
			} else {

				// Avanza con la pelota
				comandos.add(new ComandoIrA(idxOrigen, destino));
				comandos.add(new ComandoGolpearBalon(idxOrigen));
				llevoLaPelota = true;
				jugLlevaPelota = idxOrigen;
			}

		} else if (!darPase(sp, misJugadores, idxOrigen)) {

			// No avanza con la pelota ni dio pase
			// Disparar al arco
			forzarAccion(sp, idxOrigen);
		}
	}

	private void forzarAccion(SituacionPartido sp, int idxOrigen) {
		// Si el idxOrigen < 9 buscar -> buscar un un pase (despejar).
		// Si el idxOrigen >= 9 buscar -> Si coordYBalon < LINEA_LIMITE_ZONA_3
		// -> buscar un pase
		// Si el idxOrigen >= 9 buscar -> Si coordYBalon < LINEA_LIMITE_ZONA_3
		// -> marear
		if (idxOrigen < DELANTERO_IZQ) {
			patearArco(sp, idxOrigen);
		} else if (sp.balon().getY() > LINEA_ZONA_ATAQUE_Y) {
			patearArco(sp, idxOrigen);
		} else {
			// Marear si estoy lejos del arco, sino patear al arco

			double angulo = Math.PI / 4;
			double coordXPelota = sp.balon().getX();
			boolean cond1 = coordXPelota < 0;
			if (cond1) {
				if (coordXPelota < -(Constantes.ANCHO_CAMPO_JUEGO - 20) / 2) {
					angulo = Math.PI / 4;
				} else {
					angulo = -Math.PI / 4;
				}
			} else {
				if (coordXPelota < (Constantes.ANCHO_CAMPO_JUEGO - 20) / 2) {
					angulo = -Math.PI / 4;
				} else {
					angulo = Math.PI / 4;
				}
			}
			Posicion posOrigen = sp.misJugadores()[idxOrigen];
			Posicion temp = posOrigen.moverAngulo(angulo, 2);
			Posicion destino = new Posicion(temp.getX(), posOrigen.getY() + 5);
			comandos.add(new ComandoIrA(idxOrigen, destino));
			comandos.add(new ComandoGolpearBalon(idxOrigen));
			llevoLaPelota = true;
			jugLlevaPelota = idxOrigen;
		}
	}

	private void despejar(SituacionPartido sp, int idxOrigen) {

		int destino = ENGANCHE;

		double distDelDerRival = 0;
		if (idxOrigen != DELANTERO_DER) {
			distDelDerRival = ditancciaRivalMasCercano(sp, DELANTERO_DER);
		}

		double distDelIzqRival = 0;
		if (idxOrigen != DELANTERO_IZQ) {
			distDelIzqRival = ditancciaRivalMasCercano(sp, DELANTERO_IZQ);
		}

		double distEngRival = 0;
		if (idxOrigen != ENGANCHE) {
			distEngRival = ditancciaRivalMasCercano(sp, ENGANCHE);
		}

		double distMayor = Math.max(Math.max(distDelDerRival, distDelIzqRival), distEngRival);

		if (distMayor == distDelDerRival) {
			destino = DELANTERO_DER;
		} else if (distMayor == distDelIzqRival) {
			destino = DELANTERO_IZQ;
		}
		calcularPase(sp, idxOrigen, destino);
	}

	private double ditancciaRivalMasCercano(SituacionPartido sp, int destino) {
		Posicion[] misJugadores = sp.misJugadores();
		Posicion[] rivales = sp.rivales();
		int rival = misJugadores[destino].indiceMasCercano(rivales);
		return misJugadores[destino].distancia(rivales[rival]);
	}

	private boolean puedeAvanzarConPelota(SituacionPartido sp, int idxOrigen, Posicion destino) {

		boolean llevaPelota = false;

		// Posicion de mis jugadores
		Posicion[] misJugadores = sp.misJugadores();

		// Posicion del jugador origen
		Posicion posOrigen = misJugadores[idxOrigen];

		// Indices de rivales ordenados por cercania al jugador origen
		int[] rivalesCercanos = posOrigen.indicesMasCercanos(sp.rivales());

		for (int rival : rivalesCercanos) {

			// Distancia del jugador origen al rival
			double distOrigenRival = misJugadores[idxOrigen].distancia(sp.rivales()[rival]);

			// Si el jugador origen no esta marcado puede avanzar
			boolean cond1 = distOrigenRival < DISTANCIA_MIN_MARCA * 1.5;
			boolean cond2 = distOrigenRival > DISTANCIA_MIN_MARCA / 2;

			if (cond1 && cond2) {

				boolean cond3 = estaRivalEnZonaAvance(sp, idxOrigen, rival, destino);

				if (!cond3) {
					llevaPelota = true;
				} else {
					llevaPelota = false;
					break;
				}
			} else {
				break;
			}
		}

		return llevaPelota;
	}

	private boolean estaRivalEnZonaAvance(SituacionPartido sp, int idxOrigen, int rival, Posicion destino) {

		Posicion[] misJugadores = sp.misJugadores();

		// Si la diferencia de angulos es mayor a 22.5� (Math.PI / 8)
		// puede avanzar
		boolean cond2 = estaRivalEnAnguloZonaAvance(misJugadores[idxOrigen], sp.rivales()[rival], destino, Math.PI / 8);

		return cond2;
	}

	private boolean estaRivalEnAnguloZonaAvance(Posicion origen, Posicion rival, Posicion objetivo, double angulo) {

		// Angulo (respecto del origen) entre el jugador origen y el
		// objetivo (por lo general el arco rival)
		double angOrigenArco = origen.angulo(objetivo);

		// Angulo (respecto del origen) entre el jugador origen y el
		// rival
		double angOrigenRival = origen.angulo(rival);

		// Si la diferencia de angulos es mayor a angulo el rival no esta en la
		// zona de avance.
		boolean cond2 = Math.abs(angOrigenArco - angOrigenRival) < angulo;

		return cond2;
	}

	private boolean darPase(SituacionPartido sp, Posicion[] misJugadores, int idxOrigen) {
		boolean darPase = false;

		Posicion[] rivales = sp.rivales();

		// Posicion del jugador origen
		Posicion posOrigen = misJugadores[idxOrigen];

		int[] jugadoresDestino = misJugadores[idxOrigen].indicesMasCercanos(misJugadores, ARQUERO, idxOrigen);

		// Itero sobre mis jugadores ordenados por distancia
		for (int idxDestino : jugadoresDestino) {

			// Posicion del jugador destino
			Posicion posDestino = misJugadores[idxDestino];

			// Calculo la distancia entre el jugador destino y el
			// jugador origen
			double distOringenDestino = posOrigen.distancia(posDestino);

			// Para dar un pase a este jugador se debe cumplir con:
			// Si la distancia debe superar la distancia minima de
			// pase
			double distanciaMin = DISTANCIA_MIN_PASE;
			if (sp.balon().getY() > LINEA_ZONA_DEFENSA_Y) {
				distanciaMin = DISTANCIA_MIN_PASE / 2;
			}
			boolean condOD1 = distOringenDestino > distanciaMin;

			// La coordenada Y debe ser mayor a coordenada Y del
			// jugador origen menos 5
			double coordYDestino = posDestino.getY();
			double coordYOrigen = posOrigen.getY();

			boolean condOD2 = true;
			if (sp.balon().getY() < LINEA_ZONA_ATAQUE_Y) {
				condOD2 = coordYDestino > coordYOrigen - 10;
			}
			boolean condOD3 = idxOrigen < 4 ? idxDestino > 3 : true;

			if (condOD1 && condOD2 && condOD3) {

				darPase = true;

				// Indices de rivales ordenados por distancia al
				// jugador destino
				int[] rivalesCercanos = posDestino.indicesMasCercanos(rivales);
				for (int rival : rivalesCercanos) {

					// Posicion reival
					Posicion posRival = rivales[rival];

					// Discancia del jugador destino al rival
					double distDestinoRival = posDestino.distancia(posRival);

					if (distDestinoRival < DISTANCIA_MIN_PASE * 2) {
						// Para dar un pase se debe cumplir con:
						// Distancia del jugador destino al rival mayor
						// a la distancia minima de marca
						double distMinMarca = DISTANCIA_MIN_MARCA;
						if (sp.balon().getY() > LINEA_ZONA_ATAQUE_Y) {
							distMinMarca = DISTANCIA_MIN_MARCA / 2;
						}
						boolean condDR1 = distDestinoRival > distMinMarca;

						// Angulo
						// double a = posDestino.distancia(posRival);
						// double b = posOrigen.distancia(posRival);
						// double c = posOrigen.distancia(posDestino);
						//
						// double anguloRad = Math.acos(Math.pow(a, 2)
						// - Math.pow(b, 2) - Math.pow(c, 2) + 2 * b * c);
						//
						// // El valor absoluto del angulo debe ser < Math.PI /
						// 6
						// (30�)
						// boolean condDR2 = anguloRad > Math.PI / 6;

						boolean condDR2 = estaRivalEnZonaAvance(sp, idxOrigen, rival, posDestino);

						boolean condDR3 = condDR1 && !condDR2;

						if (!condDR3) {
							darPase = false;
							break;
						}
					} else {
						break;
					}

				}

				if (darPase) {
					calcularPase(sp, idxOrigen, idxDestino);
					break;
				}

			}
		}

		return darPase;
	}

	private void adoptarPosiciones(SituacionPartido sp) {

		if (sp.balon().getY() < LINEA_ZONA_DEFENSA_Y) {

			// Posicion 1
			for (int i = 0; i < 11; i++) {
				boolean esMediocampista = i == MEDIOCAMPISTA_DER || i == MEDIOCAMPISTA_IZQ;

				boolean esJugLlevaPelota = i == jugLlevaPelota;

				boolean esJugPasePelota = i == jugPasePelota;

				boolean mover = false;
				if (esMediocampista && moverMediocampistas) {
					mover = true;
				} else if (esJugLlevaPelota && llevoLaPelota) {
					mover = true;
				} else if (esJugPasePelota && paseJugador) {
					mover = true;
				} else if (!esMediocampista && !esJugLlevaPelota && !esJugPasePelota) {
					mover = true;
				}

				if (mover) {
					comandos.add(new ComandoIrA(i, alineacion1[i]));
				}
			}

			// DEFENSOR_IZQ marca a un jugador
			marcarRivalIzq(DEFENSOR_IZQ, sp);

			// DEFENSOR_DER marca a un jugador
			marcarRivalDer(DEFENSOR_DER, sp);

			if (paseJugador) {
				comandos.add(new ComandoIrA(jugPasePelota, posJugPasePelota));
			}

		} else if (sp.balon().getY() > LINEA_ZONA_ATAQUE_Y) {

			// Posicion 3
			for (int i = 0; i < 11; i++) {

				boolean esJugLlevaPelota = i == jugLlevaPelota;

				boolean esJugPasePelota = i == jugPasePelota;

				boolean mover = false;
				if (esJugLlevaPelota && llevoLaPelota) {
					mover = true;
				} else if (esJugPasePelota && paseJugador) {
					mover = true;
				} else if (!esJugLlevaPelota && !esJugPasePelota) {
					mover = true;
				}

				if (mover) {
					comandos.add(new ComandoIrA(i, alineacion3[i]));
				}
			}

			if (paseJugador) {
				comandos.add(new ComandoIrA(jugPasePelota, posJugPasePelota));
			}

		} else {

			// Posicion 2
			for (int i = 0; i < 11; i++) {

				boolean esJugLlevaPelota = i == jugLlevaPelota;

				boolean esJugPasePelota = i == jugPasePelota;

				boolean mover = false;
				if (esJugLlevaPelota && llevoLaPelota) {
					mover = true;
				} else if (esJugPasePelota && paseJugador) {
					mover = true;
				} else if (!esJugLlevaPelota && !esJugPasePelota) {
					mover = true;
				}

				if (mover) {
					comandos.add(new ComandoIrA(i, alineacion3[i]));
				}
			}

			// DEFENSOR_IZQ marca a un jugador
			marcarRivalIzq(DEFENSOR_IZQ, sp);

			// DEFENSOR_DER marca a un jugador
			marcarRivalDer(DEFENSOR_DER, sp);

			if (paseJugador) {
				comandos.add(new ComandoIrA(jugPasePelota, posJugPasePelota));
			}

		}
	}

	private void posicionarArquero(SituacionPartido sp) {
		double arqueroY = alineacion1[ARQUERO].getY();
		double dist = Constantes.LARGO_ARCO / 2;

		if (sp.balon().getX() < -Constantes.LARGO_ARCO / 2) {
			Posicion a = new Posicion(-dist, arqueroY);
			comandos.add(new ComandoIrA(ARQUERO, a));
		} else if (sp.balon().getX() > Constantes.LARGO_ARCO / 2) {
			Posicion a = new Posicion(dist, arqueroY);
			comandos.add(new ComandoIrA(ARQUERO, a));
		} else {
			Posicion a = new Posicion(sp.balon().getX(), arqueroY);
			comandos.add(new ComandoIrA(ARQUERO, a));
		}
	}

	private Posicion marcarRivalIzq(int jugador, SituacionPartido sp) {
		Posicion[] misJugadores = sp.misJugadores();
		int rivalDefIzq = misJugadores[jugador].indiceMasCercano(sp.rivales());
		Posicion rivalMarcarDefIzq = sp.rivales()[rivalDefIzq];
		if (rivalMarcarDefIzq.getY() < LINEA_ZONA_DEFENSA_Y && rivalMarcarDefIzq.getX() < 0) {
			comandos.add(new ComandoIrA(jugador, rivalMarcarDefIzq));
		}
		return rivalMarcarDefIzq;
	}

	private Posicion marcarRivalDer(int jugador, SituacionPartido sp) {
		Posicion[] misJugadores = sp.misJugadores();
		int rivalDefIzq = misJugadores[jugador].indiceMasCercano(sp.rivales());
		Posicion rivalMarcarDefIzq = sp.rivales()[rivalDefIzq];
		if (rivalMarcarDefIzq.getY() < LINEA_ZONA_DEFENSA_Y && rivalMarcarDefIzq.getX() > 0) {
			comandos.add(new ComandoIrA(jugador, rivalMarcarDefIzq));
		}
		return rivalMarcarDefIzq;
	}

	private void patearArco(SituacionPartido sp, int jugOrigen) {

		// Potencia a la que va a patear y si angulo
		double potenciaRemate = 1;
		double anguloRemate = Constantes.ANGULO_VERTICAL;
		boolean patearPrecision = false;

		// Posicion de mis jugadores
		Posicion[] misJugadores = sp.misJugadores();

		// Posicion jugador que patea
		Posicion posOrigen = misJugadores[jugOrigen];

		// Posicion arco
		Posicion posArco = Constantes.centroArcoSup;

		// disctancia entre jugador y arco
		double distancia = posOrigen.distancia(posArco);

		// Caracteristicas del jugador que patea
		JugadorDetalle detalleOrigen = sp.detalleMisJugadores()[jugOrigen];

		// Potencia de disparo del jugador que patea
		double poderPatadaOrigen = detalleOrigen.getRemate();

		boolean pateaFuerte = poderPatadaOrigen > 0.5;

		// Segun la distancia y la fuerza del ajusto la poencia y el angulo
		if (distancia < 15) {
			if (pateaFuerte) {
				potenciaRemate = 1;
				anguloRemate = Constantes.ANGULO_VERTICAL / 2;
			} else {
				potenciaRemate = 1;
				anguloRemate = Constantes.ANGULO_VERTICAL / 2;
			}
			patearPrecision = true;
		} else if (distancia < 25) {
			if (pateaFuerte) {
				potenciaRemate = 1;
				anguloRemate = Constantes.ANGULO_VERTICAL / 2;
			} else {
				potenciaRemate = 1;
				anguloRemate = Constantes.ANGULO_VERTICAL / 2;
			}
			patearPrecision = true;
		} else if (distancia < 35) {
			if (pateaFuerte) {
				potenciaRemate = 1;
				anguloRemate = 25;
			} else {
				potenciaRemate = 1;
				anguloRemate = 25;
			}
		} else if (distancia < 45) {
			if (pateaFuerte) {
				potenciaRemate = 1;
				anguloRemate = 25;
			} else {
				potenciaRemate = 1;
				anguloRemate = 25;
			}
		} else {
			if (pateaFuerte) {
				potenciaRemate = 1;
				anguloRemate = Constantes.ANGULO_VERTICAL;
			}
		}

		Posicion destino = null;

		if (patearPrecision) {

			double random = rand.nextDouble();

			double mitadArcoMenos1 = (Constantes.LARGO_ARCO / 2) - 1;
			if (random < 0.7) {
				destino = new Posicion(-mitadArcoMenos1, posArco.getY());
			} else {
				destino = new Posicion(mitadArcoMenos1, posArco.getY());
			}
		} else {
			destino = new Posicion(posArco.getX(), posArco.getY());
		}
		comandos.add(new ComandoGolpearBalon(jugOrigen, destino, potenciaRemate, anguloRemate));
		llevoLaPelota = false;
		jugLlevaPelota = 0;
		paseJugador = false;
	}

	// comandos.add(new ComandoGolpearBalon(idxOrigen,
	// Constantes.centroArcoSup, 1, 10));

	private void calcularPase(SituacionPartido sp, int jugOrigen, int jugDestino) {

		// Potencia a la que va a dar el pase y si angulo
		double potenciaPase = 1;
		double anguloPase = Constantes.ANGULO_VERTICAL;

		// Psicion de mis jugadores
		Posicion[] misJugadores = sp.misJugadores();

		// Posicion jugador origen
		Posicion posOrigen = misJugadores[jugOrigen];

		// Posicion jugador destino
		Posicion posDestino = misJugadores[jugDestino];

		// disctancia entre jugador origen y jugador destino
		double distancia = posOrigen.distancia(posDestino);

		// Caracteristicas del jugador origen
		JugadorDetalle detalleOrigen = sp.detalleMisJugadores()[jugOrigen];

		// Potencia de disparo del jugador origen
		double poderPatadaOrigen = detalleOrigen.getRemate();

		boolean pateaFuerte = poderPatadaOrigen > 0.5;

		// Segun la distancia y la fuerza del ajusto la poencia y el angulo
		if (distancia < 20) {
			if (pateaFuerte) {
				potenciaPase = 0.6;
				anguloPase = 0;
			} else {
				potenciaPase = 0.8;
				anguloPase = 0;
			}
		} else if (distancia < 30) {
			if (pateaFuerte) {
				potenciaPase = 0.8;
				anguloPase = 0;
			} else {
				potenciaPase = 1;
				anguloPase = 0;
			}
		} else if (distancia < 40) {
			if (pateaFuerte) {
				potenciaPase = 0.8;
				anguloPase = 25;
			} else {
				potenciaPase = 1;
				anguloPase = 25;
			}
		} else if (distancia < 50) {
			if (pateaFuerte) {
				potenciaPase = 0.9;
				anguloPase = 25;
			} else {
				potenciaPase = 1;
				anguloPase = 25;
			}
		} else {
			if (pateaFuerte) {
				potenciaPase = 1;
				anguloPase = 30;
			}
		}

		comandos.add(new ComandoGolpearBalon(jugOrigen, posDestino, potenciaPase, anguloPase));
		paseJugador = true;
		jugPasePelota = jugDestino;
		posJugPasePelota = posDestino;
		llevoLaPelota = false;
		jugLlevaPelota = 0;
	}

	private void avanzarDelanteros(SituacionPartido sp) {
		if (estoyAtacando && !paseJugador) {
			// Adelanto al ENGANCHE y los 2 DELANTEROS

			double anchoAreaGrande = Constantes.ANCHO_AREA_GRANDE;
			double largoAreaChica = Constantes.LARGO_AREA_GRANDE;
			Posicion posCentroArcoSup = Constantes.centroArcoSup;

			if (sp.misJugadores()[DELANTERO_IZQ].getX() < -largoAreaChica / 2) {
				comandos.add(new ComandoIrA(DELANTERO_IZQ, posCentroArcoSup));
			} else {
				Posicion a = new Posicion(-largoAreaChica / 2, posCentroArcoSup.getY() - anchoAreaGrande);
				comandos.add(new ComandoIrA(DELANTERO_IZQ, a));
			}
			if (sp.misJugadores()[DELANTERO_DER].getX() > largoAreaChica / 2) {
				comandos.add(new ComandoIrA(DELANTERO_DER, posCentroArcoSup));
			} else {
				Posicion a = new Posicion(largoAreaChica / 2, posCentroArcoSup.getY() - anchoAreaGrande);
				comandos.add(new ComandoIrA(DELANTERO_DER, a));
			}
			if (sp.misJugadores()[ENGANCHE].getY() < posCentroArcoSup.getY() - anchoAreaGrande - 10) {
				comandos.add(new ComandoIrA(ENGANCHE, posCentroArcoSup));
			} else {
				Posicion a = new Posicion(posCentroArcoSup.getX(), posCentroArcoSup.getY() - anchoAreaGrande - 10);
				comandos.add(new ComandoIrA(ENGANCHE, a));
			}
		}
	}
}
